package com.scarecrow.olga.util {
	
	import flash.utils.Dictionary;
	
	/**
	 * ...
	 * @author Santiago.J.Elizalde
	 */
	public class Cache {
		
		private var objectsById:Dictionary;
		private var idsByObject:Dictionary;
		private var cacheSize:uint;
		
		public function Cache() {
			objectsById = new Dictionary();
			idsByObject = new Dictionary();
		}
		
		/**
		 * This method tells if an object with the supplied ID is stored in the cache.
		 * 
		 * @param	objectId
		 * @return	true if the object is in cache.
		 */
		public function hasObject(objectId:String):Boolean {
			if (objectsById[objectId]) {
				return true;
			}
			return false;
		}
		
		/**
		 * Returns an object's cache ID (if the object is in the cache).
		 * 
		 * @param	object	the object to check for an ID.
		 * @return	the supplied object's cache ID.
		 */
		public function getObjectId(object:Object):String {
			return idsByObject[object];
		}
		
		/**
		 * Adds the supplied objct to the cache using the supplied ID. Unless the overrideCache parameter is set to true, 
		 * this method will not attempt to add an object that's already in cache or to add an object with an ID that is 
		 * already in use.
		 * 
		 * @param	object	the object to add to the cache under the supplied ID.
		 * @param	objectId	The ID with which to store the object in the cache.
		 * @param	overrideCache	Tells the method to erase any previous entries conflicting with the supplied object or ID.
		 * 							This parameter can be useful to change an object's ID or to change the object that is
		 * 							stored under a certain ID.
		 */
		public function addObject(object:Object, objectId:String, overrideCache:Boolean=false):void {
			
			var prevObject:Object = objectsById[objectId];
			var prevId:String = idsByObject[object];
			
			if (prevObject) {
				if (!overrideCache) {
					trace("[CACHE WARNING]@Cache.addObject() :: supplied object was not added to cache, the ID '" + objectId + "' is in use by another object.")
					return;
				} else {
					flushObject(objectId);
				}
			}
			if (prevId) {
				if (!overrideCache) {
					trace("[CACHE WARNING]@Cache.addObject() :: supplied object was not added to cache, it is already stored under a different ID:'" + prevId + "'.")
					return;
				} else {
					flushObject(prevId);
				}
			}
			
			objectsById[objectId] = object;
			idsByObject[object] = objectId;
			cacheSize++;
		}
		
		/**
		 * This method retrieves an object from the cache, using the supplied ID as the key.
		 * 
		 * @param	objectId	The cache ID of the object you wish to retrieve.
		 */
		public function getObject(objectId:String):void {
			return objectsById[objectId]
		}
		
		/**
		 * Flushes (deletes) an entry from the cache.
		 * @param	objectId the ID of the object to delete.
		 */
		public function flushObject(objectId:String):void {
			
			if (!hasObject(objectId)) {
				trace("[CACHE WARNING]@Cache.flushObject() :: unable to flush supplied object with ID '" + prevId + "', the object is not stored in cache.")
				return;
			}
			
			var flushedObject:Object = objectsById[objectId];
			delete idsByObject[flushedObject]
			delete objectsById[objectId];
			cacheSize--;
		}
		
		/**
		 * Flushes (deletes) all elements from the cache, emptying it.
		 */
		public function flushAll():void {
			objectsById = new Dictionary();
			idsByObject = new Dictionary();
			cacheSize = 0;
		}
		
		/**
		 * Returns the amount of entries in the Cache object.
		 */
		public function get size():uint {
			return cacheSize;
		}
	}

}